nuart = require("@native.uart");
sys = require("@native.builtin");
error = require("error.js")

__FILE__ = "uart.js";

ERR = new error.ThrowError(__FILE__);

DATABITS_5        = 5;
DATABITS_6        = 6;
DATABITS_7        = 7;
DATABITS_8        = 8;
DATABITS_9        = 9;


STOPBITS_1        = 0;
STOPBITS_1_5      = 1;
STOPBITS_2        = 2;

PARITY_NONE       = 0;
PARITY_ODD        = 1;
PARITY_EVEN       = 2;

function Uart(id){
    this.__module__ = "uart";
    this.__id__ = -1;

    this.id = id;

    this.write = function(buffer){
        if(buffer == undefined || buffer.length == 0)
            return undefined;
        var size = buffer.length;
        var data = sys.malloc(size);
        if(data == null)
            return undefined;
        var ret = sys.copy(data, buffer, size);
        if(ret == false){
            sys.free(data);
            return undefined;
        }
        nuart.write(this.id, data, size);
        sys.free(data);
    }
    this.readAssert = function(opt){
        if(opt == undefined)
            return undefined;
        if(opt["len"] == undefined || typeof(opt["len"]) != "number" || opt["len"] == 0)
            return undefined;

        if(opt["timeout"] == undefined || typeof(opt["timeout"]) != "number")
            return undefined;
        return opt;
    }

    this.read = function(opt){
        opt = this.readAssert(opt);
        if(opt == undefined){
            ERR.trace("read", 61, "ERR_ARGS_INVID","opt assert failed")
            return undefined;
        }

        var len = opt["len"];
        var timeout = opt["timeout"];

        var buffer = sys.malloc(len);
        if(buffer == null){
            ERR.trace("read", 69, "ERR_MEM_INVID","opt assert failed")
            return undefined;
        }
        var ret = nuart.read(this.id, buffer, len, timeout);
        if(ret < 0){
            sys.free(buffer);
            return undefined;
        }
        var data = sys.toJsArray(buffer, len);
        sys.free(buffer);
        return data;
    }

    this.on = function(event, callback){
        if(event != "recv")
            return undefined;

        this.__id__ = globalThis.eventbus.on(this, event, callback);
        nuart.on(this.id, this.__id__, event);
    }

    this.close = function(){
        nuart.close(this.id);
    }
}

function open(obj){
    var id = obj["id"];
    if(id == undefined || typeof(id) != "number")
        return undefined;
    var baud = obj["baud"];
    if(baud == undefined || typeof(baud) != "number"){
        baud = 115200;
    }
    var databits = obj["databits"];
    if(databits == undefined || typeof(databits) != "number"){
        databits = DATABITS_8;
    }

    var stopbits = obj["stopbits"];
    if(stopbits == undefined || typeof(stopbits) != "number"){
        stopbits = STOPBITS_1;
    }

    var parity = obj["parity"];
    if(parity == undefined || typeof(parity) != "number"){
        parity = PARITY_NONE;
    }

    var buffersize = obj["buffersize"];
    if(buffersize == undefined || typeof(buffersize) != "number"){
        buffersize = 512;
    }
    if(nuart.open(id, baud, databits, stopbits, parity, buffersize) == 0){
        return new Uart(id);
    }
    return undefined;
}